/*
 * Copyright 2010 Katsunori Koyanagi
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package sweezy.anim.updater.geom
{
	import flash.display.DisplayObject;
	import flash.geom.Matrix;
	import sweezy.anim.core.IPropertyAnimation;
	import sweezy.anim.core.IUpdater;
	import sweezy.anim.updater.UpdaterProperty;

	public class MatrixUpdater implements IUpdater
	{

		public function MatrixUpdater()
		{
		}

		public function initialize(element:Object, property:UpdaterProperty, prefix:String, option:Object, target:IPropertyAnimation):void
		{
			var matrix:Matrix = getMatrix(element);

			while (property !== null)
			{
				if (isNaN(property.end))
				{
					property.end = 0;
				}
				if (isNaN(property.start))
				{
					property.name === "a" ? property.start = matrix.a :
						property.name === "b" ? property.start = matrix.b :
						property.name === "c" ? property.start = matrix.c :
						property.name === "d" ? property.start = matrix.d :
						property.name === "tx" ? property.start = matrix.tx :
						property.name === "ty" ? property.start = matrix.ty :
						property.start = 0;
				}
				if (property.relative)
				{
					property.end += property.start;
				}

				property = property.next;
			}
		}

		public function update(element:Object, property:UpdaterProperty, prefix:String, fraction:Number, option:Object, target:IPropertyAnimation):void
		{
			var matrix:Matrix = getMatrix(element);
			var value:Number;

			while (property !== null)
			{
				value = property.start + (property.end - property.start) * fraction;
				value = property.round ? ((value * 2 | 0) - (value | 0)) : value;

				property.name === "a" ? matrix.a = value :
					property.name === "b" ? matrix.b = value :
					property.name === "c" ? matrix.c = value :
					property.name === "d" ? matrix.d = value :
					property.name === "tx" ? matrix.tx = value :
					property.name === "ty" ? matrix.ty = value :
					null;
				property = property.next;
			}

			if (element is DisplayObject)
			{
				(element as DisplayObject).transform.matrix = matrix;
			}
		}

		private function getMatrix(element:Object):Matrix
		{
			var matrix:Matrix;

			if (element is DisplayObject)
			{
				var d:DisplayObject = element as DisplayObject;
				matrix = element.transform.matrix;
				if (matrix === null)
				{

					var r:Number = d.rotation;
					var sx:Number = d.scaleX;
					var sy:Number = d.scaleY;
					var cos:Number = Math.cos(0.017453292519943295 * r);
					var sin:Number = Math.sin(0.017453292519943295 * r);

					matrix = new Matrix();
					matrix.a = sx * cos;
					matrix.b = sx * sin;
					matrix.c = sy * -sin;
					matrix.d = sy * cos;
					matrix.tx = d.x;
					matrix.ty = d.y;

					d.transform.matrix = matrix;
				}
			}
			else
			{
				matrix = element as Matrix;
			}

			return matrix;
		}
	}
}
